feat(tui): redesign shell, fix scrolling, auth and daemon polling - #12
Merged
Conversation
The TUI gets a left sidebar, a mint-on-ink palette (src/tui/theme.rs), mouse support and a redrawn dashboard. Review follow-ups folded in: Correctness - Login: `q` was bound to quit under an `if password.is_empty()` guard that applied to the whole or-pattern, making every password starting with `q` unenterable. Quit is now Esc-on-empty (plus Ctrl+C/Ctrl+D). - `G` set scroll_offset to the last *index*; every screen renders `.skip(scroll_offset)`, so it collapsed the list to a single row. Added `max_offset(len, visible)` — the top of the last page — and a clamp pass on render so a resize or a shrinking list cannot strand the viewport. - Routes counted unfiltered rules for selection bounds while rendering the filtered list, and resolved the cursor back to a rule with a *different* predicate (matcher Debug vs format_matcher) than the one it displayed — a search could line a row up with a rule other than the one `d` deleted. Both now share `screens::routes::filter_indices`. - Config screen could not scroll at all: get_max_selection returned 0, so move_selection bailed. Added a text-viewport scroll path and cached the file contents instead of re-reading them every frame. - tail_file used read_to_string, so a seek landing mid-codepoint (or any non-UTF-8 byte) blanked the log viewer with no explanation. Reads bytes and converts lossily; open/read errors now name the path and cause. Responsiveness - Daemon metrics moved off the render thread into a background poller. The inline block_on froze the UI for the request timeout every tick, worst exactly when the daemon was down. The client is built once, not per tick. - Mouse reporting uses ?1000/?1006 rather than crossterm's EnableMouseCapture, which also enables ?1003 any-motion tracking: a redraw per pointer movement, and terminal text selection taken away from the user (the OSC-52 fallback). - The event loop only repaints when something changed. Reporting - daemon_ok: bool -> DaemonStatus. A proxy running with `admin.enabled = false` is healthy; it was reported as "daemon down". Metric panes now show why they are empty instead of a confident 0. - Dashboard regained listen/https/tls/admin/auth/scripts, in-flight, bytes in/out, TLS connections, half-open circuits and the apps overflow hint. Docs - docs/tui-screenshots depicted a UI that was never built (top tabs, cyan palette, panels since removed). Regenerated against the shipped layout, with a README stating they are mockups and where each element's source of truth lives. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`cargo clippy -- -D warnings` failed on `result_large_err`: the function returns a `u16` on success against a `Response<BoxBody>` (128+ bytes) on failure, so every call paid for the error variant. Pre-existing — main fails the same lint. It surfaced now because CI pins `dtolnay/rust-toolchain@stable`, which has moved past the clippy release the last green run used, while mise.toml pins 1.93.0 locally. Every caller immediately returns the error as its own response, so boxing it costs an allocation only on the error path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The TUI gets a left sidebar, a mint-on-ink palette (src/tui/theme.rs), mouse support and a redrawn dashboard. Review follow-ups folded in:
Correctness
qwas bound to quit under anif password.is_empty()guard that applied to the whole or-pattern, making every password starting withqunenterable. Quit is now Esc-on-empty (plus Ctrl+C/Ctrl+D).Gset scroll_offset to the last index; every screen renders.skip(scroll_offset), so it collapsed the list to a single row. Addedmax_offset(len, visible)— the top of the last page — and a clamp pass on render so a resize or a shrinking list cannot strand the viewport.ddeleted. Both now sharescreens::routes::filter_indices.Responsiveness
Reporting
admin.enabled = falseis healthy; it was reported as "daemon down". Metric panes now show why they are empty instead of a confident 0.Docs